<!DOCTYPE html>
<!-- saved from url=(0106)https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust?display=Print -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>Custom Controls in Win32 API: Encapsulation of Customized Controls - CodeProject</title> 
	<link type="text/css" rel="stylesheet" href="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/Main.min.css">

	
<meta http-equiv="content-language" content="en-US">

<meta name="Description" content="Few techniques for getting rid of customized-control-specific code from parent window procedure.; Author: Martin Mitáš; Updated: 11 Dec 2014; Section: Windows API; Chapter: Platforms, Frameworks &amp; Libraries; Updated: 11 Dec 2014">
<meta name="Keywords" content="C, Windows, Win32, Win64, Dev,Windows API,Platforms, Frameworks &amp; Libraries,Free source code, tutorials">
<meta name="Author" content="Martin Mitáš">
<meta name="Rating" content="General">
<meta name="Revisit-After" content="1 days">
<meta name="application-name" content="CodeProject">
<meta name="google-translate-customization" content="d908bb7ce7aff658-4c2f3a504525c916-g629383f736781a8a-13">

<link rel="dns-prefetch" href="https://ajax.googleapis.com/"> 
<link rel="canonical" href="https://www.codeproject.com/Articles/744603/%2fArticles%2f744603%2fCustom-Controls-in-Win-API-Encapsulation-of-Cust">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - All Topics" href="https://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=1">
<link rel="alternate" type="application/rss+xml" title="CodeProject Latest articles - Artificial Intelligence" href="https://www.codeproject.com/WebServices/ArticleRSS.aspx?cat=31">
<link rel="alternate" type="application/rss+xml" title="CodeProject Lounge Postings" href="https://www.codeproject.com/webservices/LoungeRSS.aspx">
<meta name="robots" content="index, follow">
<link rel="search" type="application/opensearchdescription+xml" title="CodeProject" href="https://www.codeproject.com/info/OpenSearch.xml">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="apple-touch-icon" sizes="144x144" href="https://www.codeproject.com/favicon/apple-touch-icon.png"> 
<link rel="icon" type="image/png" sizes="32x32" href="https://www.codeproject.com/favicon/favicon-32x32.png"> 
<link rel="icon" type="image/png" sizes="16x16" href="https://www.codeproject.com/favicon/favicon-16x16.png"> 
<link rel="manifest" href="https://www.codeproject.com/favicon/manifest.json"> 
<link rel="mask-icon" href="https://www.codeproject.com/favicon/safari-pinned-tab.svg" color="#ff9900">
	
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "TechArticle",
  "headline": "Custom Controls in Win32 API: Encapsulation of Customized Controls",
  "url": "https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust",
  "discussionUrl": "https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust",
  "isFamilyFriendly": "true",
  "image": "https://codeproject.global.ssl.fastly.net/App_Themes/CodeProject/Img/Article100.png",
  "keywords": "C, Windows, Win32, Win64",
  "commentCount": "4",
  "editor" : {
    "@type" : "Person",
    "name" : "Martin Mitáš",
    "url" : "https://www.codeproject.com/script/Membership/View.aspx?mid=5807385"
  },
  "license": "http://www.codeproject.com/info/cpol10.aspx",
  "publisher" : {
    "@type" : "Organization",
    "name" : "CodeProject"
  }
  "description": "Few techniques for getting rid of customized-control-specific code from parent window procedure.",
  "upvoteCount": "22",
  "articleSection": "Windows API",
  "author" : [{
      "@type" : "Person",
      "name" : "Martin Mitáš",
      "url" : "https://www.codeproject.com/script/Membership/View.aspx?mid=5807385"
    }],
  "datePublished": "2014-12-11",
  "dateCreated": "2014-12-11",
  "dateModified": "2014-12-11",
  "aggregateRating" : {
    "@type" : "aggregateRating",
    "ratingValue" : 4.87,
    "ratingCount" : 22,
    "bestRating" : 5,
    "worstRating" : 1
  },
}
</script>
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [{
    "@type": "ListItem",
    "position": 1,
    "item" : {
      "@id" : "/Chapters/8/Platforms-Frameworks-Libraries.aspx",
      "name" : "Platforms, Frameworks & Libraries"
    }
  },{
    "@type": "ListItem",
    "position": 2,
    "item" : {
      "@id" : "/KB/vista/",
      "name" : "Windows API"
    }
  }]
}
</script>
	<!--<base target="_top">--><base href="." target="_top">
	<script type="text/javascript" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/jquery.2.2.4.min.js.下载"></script><script type="text/javascript">//<![CDATA[
if (typeof jQuery == 'undefined') {
    document.write(unescape("%3Cscript src='%2fscript%2fJS%2fjquery-2.2.4.min.js' type='text/javascript' %3E%3C/script%3E"));
}//]]></script><script src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/jquery-2.2.4.min.js.下载" type="text/javascript"></script>
<script type="text/javascript">//<![CDATA[
function defrm () { /* thanks twitter */ document.write = ''; window.top.location = window.self.location;  setTimeout(function() { document.body.innerHTML = ''; }, 0);  window.self.onload = function(evt) { document.body.innerHTML = ''; }; }if (window.top !== window.self) {  try {  if (window.top.location.host) { /* will throw */ } else { defrm(); /* chrome */ }  } catch (ex) { defrm(); /* everyone else */ } }if (typeof(DemoUrl)!='undefined')   document.write(unescape('%3Cme')+'ta http'+'-equiv="re'+'fresh"                  con'+'tent="1;url='+DemoUrl+unescape('"%3CE'));

//]]>
</script>

	




<script type="text/javascript">
	var _gaq = _gaq || [];
	_gaq.push(['_setAccount', 'UA-1735123-1']);
	_gaq.push(['_trackPageview']);
	_gaq.push(['_setDomainName', 'www.codeproject.com']);
	_gaq.push(['_setSessionTimeout', '1200']); 

	(function () {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
	})(); 
</script><script type="text/javascript" async="" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/ga.js.下载"></script>


</head>	

<body class="chrome chrome67 touch">

<a class="access-link" href="https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust?display=Print#Main"><img alt="Click here to Skip to main content" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/t.gif"></a>





<div class="page-background">

	
	

	

	
    <div id="ctl00_STM" class="site-top-menu fluid">
        <div class="main-content">
            
        </div>
    </div>

	
    <div id="ctl00_SH" class="site-header fluid">
        <div class="main-content">
            <div class="logo"><a href="https://www.codeproject.com/"><img id="ctl00_Logo" tabindex="1" title="CodeProject" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/logo250x135.gif" alt="Home" style="height:135px;width:250px;border-width:0px;"></a></div>
            <div class="promo"></div>
        </div>
    </div>

	<a href="https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust?display=Print#Main"><img alt="Click here to Skip to main content" class="access-link" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/t.gif"></a>

	
			
	

	<div id="A" class="container-content-wrap fluid print"> 
	<div class="container-content">


		<div class="clearfix">
			<div class="container-breadcrumb float-left ">
				<div><a href="https://www.codeproject.com/script/Content/SiteMap.aspx">Articles</a> » <a href="https://www.codeproject.com/Chapters/8/Platforms-Frameworks-Libraries.aspx">Platforms, Frameworks &amp; Libraries</a> » <a href="https://www.codeproject.com/KB/vista/">Windows API</a> » <a href="https://www.codeproject.com/KB/vista/#General">General</a></div>
			</div>

            <div class="float-left">
				
			</div>

			<div class="edit-links float-right">
				
			</div>

			<div class="article-nav float-right">
                
				
			</div>
		</div>

		<table class="extended container-article-parts" cellpadding="0" cellspacing="0">
        <tbody><tr valign="top">
		<td width="117px" class="article-wing-left">

			

		</td>
		<td>
			
			<div id="AT" class="container-article  fluid tight"> 

				<div class="article">

					<form name="aspnetForm" method="post" action="https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust?display=Print" id="aspnetForm" style="margin:0;padding:0">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="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">
</div>

<div>

	<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="10C1FD69">
</div>

					
					 
					<div class="header">
					    <a name="Main"></a>

					    
					    <a name="_articleTop" id="_articleTop"></a>
					    <div class="title">
					        <h1 id="ctl00_ArticleTitle">Custom Controls in Win32 API: Encapsulation of Customized Controls</h1>
					    </div>

                        <div style="height:34px">
					        
					        <div class="entry float-left">

                                <img src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/58de2d085c17e28b8951315245dd408c.jpeg" id="ctl00_avatar" class="float-left avatar">

                                <div class="float-left">
                                    <div>
						                <span class="author"><a href="https://www.codeproject.com/script/Membership/View.aspx?mid=5807385" rel="author">Martin Mitáš</a></span>, 
						                <span class="date" title="Date last updated">
							            12 Dec 2014</span>
			                        </div>

                                    
						            
    						        	

                                </div>

    	                        	
                                <div class="float-left" style="margin: 25px 0 0 10px;">
	                                
	                            </div>
                         	    	
    
					        </div>

                            

						    <div id="ctl00_AdManagerWrap" class="float-right align-center">
                                
						    </div>

                        </div>

                        <div id="ctl00_description" class="summary">Few techniques for getting rid of customized-control-specific code from parent window procedure.</div><span id="ctl00_thumbnailUrl" class="date" content="https://codeproject.global.ssl.fastly.net/script/Articles/Images/article100x80.png"></span>			

                    </div>
                    
					
					

					

					
					
					

						
					

					

						
						<div id="contentdiv" class="text">
						



<h2>Articles in this series</h2>

<ul>
	<li><a href="http://www.codeproject.com/Articles/559385/Custom-Controls-in-Win32-API-The-Basics">Custom Controls in Win32 API: The Basics</a></li>	<li><a href="http://www.codeproject.com/Articles/617212/Custom-Controls-in-Win32-API-The-Painting">Custom Controls in Win32 API: The Painting</a></li>	<li><a href="http://www.codeproject.com/Articles/620045/Custom-Controls-in-Win32-API-Visual-Styles">Custom Controls in Win32 API: Visual Styles</a></li>	<li><a href="http://www.codeproject.com/Articles/624495/Custom-Controls-in-Win32-API-Standard-Messages">Custom Controls in Win32 API: Standard Messages</a></li>	<li><a href="http://www.codeproject.com/Articles/646482/Custom-Controls-in-Win-API-Control-Customization">Custom Controls in Win32 API: Control Customization</a></li>	<li>Custom Controls in Win32 API: Encapsulation of Customized Controls</li>	<li><a href="http://www.codeproject.com/Articles/1042516/Custom-Controls-in-Win-API-Scrolling">Custom Controls in Win32 API: Scrolling</a></li></ul>

<h2>Introduction</h2>

<p><a href="http://www.codeproject.com/Articles/646482/Custom-Controls-in-Win-API-Control-Customization">The last time</a>, we have discussed some techniques for customization of controls. However we saw that more or less all the techniques require some level of direct cooperation between the code customizing the control and the procedure of the parent window (usually the dialog or top-level window). If you briefly take a look on the customization techniques presented in the previous article, you can see that owner drawing, custom drawing and notifications even require by design an active cooperation of the parent window procedure.</p>

<p>At the first glance, superclassing and subclassing look better from this point of view. But in practice, complex customization need to follow changes in the underlying control logic. For example, if the superclassed or subclassed control overrides <code>WM_PAINT</code>, it may need to be informed when internal state of the control changes so it can paint the control in the right way. Usually the underlying control informs the world by sending the notification to its parent window, so the easiest solution is to catch the notification in the parent and resend it back to the customized control so it's customized window procedure can handle it. Hence even superclassing and subclassing share the problem as well.</p>

<p>That has a fundamental impact: Reuse of such controls in other dialogs or applications is more complicated, as the logic from the parent window needs to be reimplemented in new one. Hence, we will try to address this problem in this article.</p>

<p>Software engineers already recognized many years ago that encapsulation of logically related code is a desired property of a reusable code. In OOP (object-oriented programming) paradigm, the encapsulation is even one of the most important and central points. The encapsulation allows to easily take the reusable code and reuse it in other module of the application, or even outside of it (e.g. to a standalone library, so it can even be reused in other applications). It is also much easier to read, review and maintain such code, as it allows a reader to mentally split the application code into smaller, palatable bits.</p>

<p>Although OOP guides and manuals speak mainly about classes, I believe the concept is very valuable on all application design levels: When breaking the application into the core program and set of libraries, when splitting the code into source files with understandable public interface and, in our context, also the customized controls.</p>

<p>I do not say that encapsulating every Win32 control you ever customize is a good idea. If you have a single instance of a customized control in your application, the given control is logically bound to the parent window and you know you will never need to reuse the control elsewhere, feel free to be lazy. Actually the encapsulation code could be more complex then the customization itself and it may not be worth of the gains.</p>

<p>But if your customized control needs to be reused in multiple dialogs, if its handling in parent window's code is complex, if the dialog procedure is complicated on its own, if your dialog procedure needs to understand internal details of logic in the control although it has nothing to do with the higher logic of the application, then the encapsulation may provide you interesting benefits.</p>

<p>So, what does the encapsulation for the customized control actually means? It means that every logic we want to mentally understand as an implementation of the control, goes out from the parent window procedure, that it is separated from it. If you once more take a look on all customization techniques presented in the previous article, you may notice that the parent window procedure actually has to handle some notifications sent by the customized control.</p>

<h2>Wrapper Window</h2>

<p>The obvious solution of the problem is to wrap the customized control in another window, wrapping the control to the outside world.</p>

<p>The wrapper window is parent of the core control we customize and it implements all the stuff which has to be in parent window procedure of a customized control. I.e. it tracks the notifications from the customized control (the original control procedure) and it can also cooperate tightly with the subclass or superclass procedure.</p>

<p>To the outside world, the wrapper simply <b>is</b> the control. From point of the view if the application, the child of the wrapper which does majority of the work is just an implementation detail of the control and the application should not care about it at all.</p>

<p>So the wrapper actually serves as a proxy between the application (the dialog procedure) and the core control (the child window). I.e. the wrapper has to understand all messages which constitute the public API of the customized control and (in most cases) it re-sends them to the child. Similarly, the wrapper resends all publicly visible notifications sent by the child up to application.</p>

<p>As straightforward as this approach is, it is also somewhat clumsy and inelegant: The existence of the wrapper just means an unnecessary layer of indirection in your application, which eats some system resources associated with <code>HWND</code> handle, yet it actually does no useful work with the exception of some wiring. Additionally it makes the tree hierarchy of all windows one level deeper, which may impose some negative implications for utilities looking at the hierarchy via Windows Automation API or Accessibility API.</p>

<h2>Message Reflection</h2>

<p>Better way how to deal with that problem is resending the notifications (and other notification-like messages) from the dialog procedure back to the control itself and handle them directly in superclass or subclass procedure instead of the wrapper window. In the world of Win32 development, this technique is so common that it has its own name: message reflection.</p>

<p>The Win32API header <tt>olectl.h</tt> contains the following preprocessor macro definitions:</p>

<pre lang="C"><span class="code-preprocessor">#define OCM__BASE             (WM_USER+0x1c00)
</span><span class="code-preprocessor">#define OCM_COMMAND           (OCM__BASE + WM_COMMAND)
</span> 
<span class="code-preprocessor">#define OCM_CTLCOLORBTN       (OCM__BASE + WM_CTLCOLORBTN)
</span><span class="code-preprocessor">#define OCM_CTLCOLOREDIT      (OCM__BASE + WM_CTLCOLOREDIT)
</span><span class="code-preprocessor">#define OCM_CTLCOLORDLG       (OCM__BASE + WM_CTLCOLORDLG)
</span><span class="code-preprocessor">#define OCM_CTLCOLORLISTBOX   (OCM__BASE + WM_CTLCOLORLISTBOX)
</span><span class="code-preprocessor">#define OCM_CTLCOLORMSGBOX    (OCM__BASE + WM_CTLCOLORMSGBOX)
</span><span class="code-preprocessor">#define OCM_CTLCOLORSCROLLBAR (OCM__BASE + WM_CTLCOLORSCROLLBAR)
</span><span class="code-preprocessor">#define OCM_CTLCOLORSTATIC    (OCM__BASE + WM_CTLCOLORSTATIC)
</span> 
<span class="code-preprocessor">#define OCM_DRAWITEM          (OCM__BASE + WM_DRAWITEM)
</span><span class="code-preprocessor">#define OCM_MEASUREITEM       (OCM__BASE + WM_MEASUREITEM)
</span><span class="code-preprocessor">#define OCM_DELETEITEM        (OCM__BASE + WM_DELETEITEM)
</span><span class="code-preprocessor">#define OCM_VKEYTOITEM        (OCM__BASE + WM_VKEYTOITEM)
</span><span class="code-preprocessor">#define OCM_CHARTOITEM        (OCM__BASE + WM_CHARTOITEM)
</span><span class="code-preprocessor">#define OCM_COMPAREITEM       (OCM__BASE + WM_COMPAREITEM)
</span><span class="code-preprocessor">#define OCM_HSCROLL           (OCM__BASE + WM_HSCROLL)
</span><span class="code-preprocessor">#define OCM_VSCROLL           (OCM__BASE + WM_VSCROLL)
</span><span class="code-preprocessor">#define OCM_PARENTNOTIFY      (OCM__BASE + WM_PARENTNOTIFY)
</span><span class="code-preprocessor">#define OCM_NOTIFY            (OCM__BASE + WM_NOTIFY)</span></pre>

<p>As you can see, all Win32API notification and notification-like messages do have its counterpart with the <tt>OCM_</tt> prefix, whose numeric ID is increased by <code>OCM__BASE</code>.</p>

<p>Using these macros, implementing the message reflection in your parent window procedure is then quite straightforward:</p>

<ol>
	<li>The parent window's code needs to handle the standard <code>WM_xxxx</code> messages in the list above.</li>	<li>If the message is sent by a customized control who wants to handle the message itself, the parent window needs to send the corresponding <code>OCM_xxxx</code> message (with the original <code>WPARAM</code> and <code>LPARAM</code> values) to the control.</li>	<li>The superclass or subclass procedure of the control should handle the <code>OCM_xxxx</code> message, or just return zero.</li></ol>

<p>The only unclear thing may be the point 2: How can the parent know which controls expect some messages to be reflected? In simple dialogs with few controls, you can simply know IDs of few controls which need such treatment and hardcode them in the parent's procedure.</p>

<p>But there is also simple generic way: Assuming all the control are well-designed and they reserve the range of listed <code>OCM_xxxx</code> for the purpose of message reflection, the parent may by default resend all such messages to any control when it has no better idea what to do with the message. (Note that reserving the range 0x2000 (<code>OCM_BASE</code>) through 0x23ff (<code>OCM_BASE+WM_USER-1</code>) was suggested in <a href="http://www.codeproject.com/Articles/559385/Custom-Controls-in-Win32-API-The-Basics">Custom Controls in Win32 API: The Basics</a>.)</p>

<p>When sent to such polite uncustomized control which does not handle the <code>OCM_xxxx</code> messages, it is just passed to <code>DefWindowProc()</code>. That function has no idea what to do with <code>OCM_xxxx</code> messages, so it does nothing and just returns zero.</p>

<p>Below is a code snippet showing how the reflection can be handled. Surely, the reflection could be scattered in all relevant message handlers directly, but the code below isolates the reflection to a single place, the <code>DefParentProc()</code>, which is our wrapper of standard <code>DefWindowProc()</code>, and which can be reused by all parent window procedures in your application.</p>

<pre lang="C"><span class="code-keyword">#include</span><span class="code-preprocessor"> <span class="code-keyword">&lt;</span><span class="code-leadattribute">olectl.h</span><span class="code-keyword">&gt;</span>
</span>
<span class="code-keyword">static</span> LRESULT
DefParentProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    <span class="code-keyword">switch</span>(uMsg) {
        <span class="code-keyword">case</span> WM_NOTIFY:
        {
            NMHDR* nmhdr = (NMHDR*) lParam;
            <span class="code-keyword">if</span>(nmhdr-&gt;hwndFrom != NULL)
                <span class="code-keyword">return</span> SendMessage(nmhdr-&gt;hwndFrom, uMsg + OCM__BASE, wParam, lParam);
            <span class="code-keyword">break</span>;
        }

        <span class="code-comment">//</span><span class="code-comment"> All of these provide the control's HHWND in LPARAM</span>
        <span class="code-keyword">case</span> WM_COMMAND:
        <span class="code-keyword">case</span> WM_CTLCOLORBTN:
        <span class="code-keyword">case</span> WM_CTLCOLOREDIT:
        <span class="code-keyword">case</span> WM_CTLCOLORDLG:
        <span class="code-keyword">case</span> WM_CTLCOLORLISTBOX:
        <span class="code-keyword">case</span> WM_CTLCOLORMSGBOX:
        <span class="code-keyword">case</span> WM_CTLCOLORSCROLLBAR:
        <span class="code-keyword">case</span> WM_CTLCOLORSTATIC:
        <span class="code-keyword">case</span> WM_VKEYTOITEM:
        <span class="code-keyword">case</span> WM_CHARTOITEM:
            <span class="code-keyword">if</span>(lParam != <span class="code-digit">0</span>)
               <span class="code-keyword">return</span> SendMessage((HWND) lParam, uMsg + OCM__BASE, wParam, lParam);
            <span class="code-keyword">break</span>;

        <span class="code-comment">//</span><span class="code-comment"> All of these provide ID of the control in WPARAM:</span>
        <span class="code-keyword">case</span> WM_DRAWITEM:
        <span class="code-keyword">case</span> WM_MEASUREITEM:
        <span class="code-keyword">case</span> WM_DELETEITEM:
        <span class="code-keyword">case</span> WM_COMPAREITEM:
            <span class="code-keyword">if</span>(wParam != <span class="code-digit">0</span>) {
                HWND hwndControl = GetDlgItem(hwnd, wParam);
                <span class="code-keyword">if</span>(hwndControl)
                    <span class="code-keyword">return</span> SendMessage(hwndControl, uMsg + OCM__BASE, wParam, lParam);
            }
            <span class="code-keyword">break</span>;

         <span class="code-comment">//</span><span class="code-comment"> Note we do not reflect WM_PARENTNOTIFY -&gt; OCM_PARENTNOTIFY as that </span>
         <span class="code-comment">//</span><span class="code-comment"> usually does not make much sense.</span>
     }
     
     <span class="code-keyword">return</span> DefWindowProc(hwnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK
MainWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    <span class="code-keyword">switch</span>(uMsg) {
        <span class="code-keyword">case</span> WM_COMMAND:
            <span class="code-keyword">switch</span>(HIWORD(wParam)) {
                <span class="code-keyword">case</span> ID_SOMECONTROL:
                    ...  <span class="code-comment">//</span><span class="code-comment"> Handle some control explicitly</span>
                    <span class="code-keyword">return</span> <span class="code-digit">0</span>;
                <span class="code-keyword">case</span> ID_OTHERCONTROL:
                    ...  <span class="code-comment">//</span><span class="code-comment"> Handle other control explicitly</span>
                    <span class="code-keyword">return</span> <span class="code-digit">0</span>;
            }
            <span class="code-keyword">break</span>;  <span class="code-comment">//</span><span class="code-comment"> Propagate the message into DefParentProc() below.</span>

        <span class="code-keyword">case</span> WM_NOTIFY:
            <span class="code-keyword">switch</span>(wParam) {
                <span class="code-keyword">case</span> ID_SOMECONTROL:
                    ...  <span class="code-comment">//</span><span class="code-comment"> Handle some control explicitly</span>
                    <span class="code-keyword">return</span> <span class="code-digit">0</span>;
                <span class="code-keyword">case</span> ID_OTHERCONTROL:
                    ...  <span class="code-comment">//</span><span class="code-comment"> Handle other control explicitly</span>
                    <span class="code-keyword">return</span> <span class="code-digit">0</span>;
            }
            <span class="code-keyword">break</span>;  <span class="code-comment">//</span><span class="code-comment"> Propagate the message into DefParentProc() below.</span>

    
        ... <span class="code-comment">//</span><span class="code-comment"> and so one for all messages the parent needs to handle explicitly</span>
    }

    <span class="code-comment">//</span><span class="code-comment"> Pass unhandled messages into DefParentProc()</span>
    <span class="code-keyword">return</span> DefParentProc(hwnd, uMsg, wParam, lParam);
}</pre>

<h2>Injected Message Reflection</h2>

<p>Strictly speaking, the message reflection, as presented in the previous section, does not reach full code encapsulation. Although it can be realized in a generic way, the parent still has to provide some cooperation with the child controls (i.e. perform the reflection).</p>

<p>When the parent window procedure is not under our direct control, or when requirements for re-usability of the control are so high you want to avoid need for any special treatment of the control in parent window procedure, we ned to be able to get the notifications from the original control procedure in the customization (superclass or subclass) procedure.</p>

<p>With some more work, that can be achieved. And it may be achieved with technique you should already know from the previous article: The subclassing. The control may, during its creation (<code>WM_NCCREATE</code>), customize its parent window and force it to do the reflection.</p>

<p>However we need to be careful: We cannot blindly reflect messages for all child controls as we do not have any idea what the parent procedure handles and what it does not as we do not want to clash with it. In example below, we solve this by keeping a list of controls for which to do the reflection. The parent subclass procedure consults the list and if the <code>HWND</code> is present, it does the reflection instead of calling the original window procedure.</p>

<p>This has one side effect: The parent window cannot override the behavior, but arguably, it may even be an advantage: The customized control sees the notifications sent by the underlying original control and parent cannot break its logic in any way.</p>

<pre lang="C"><span class="code-keyword">#include</span><span class="code-preprocessor"> <span class="code-keyword">&lt;</span><span class="code-leadattribute">olectl.h</span><span class="code-keyword">&gt;</span>
</span>
<span class="code-comment">//</span><span class="code-comment"> A container keeping list of the HWND handles for controls which need the message reflection.</span>
<span class="code-comment">//</span><span class="code-comment"> (Its implementation is left to the reader as an exercise.)</span>
<span class="code-keyword">typedef</span> <span class="code-keyword">struct</span> { ... } CONTROL_LIST;

CONTROL_LIST* ControlListCreate(<span class="code-keyword">void</span>);
<span class="code-keyword">void</span> ControlListDestroy(CONTROL_LIST* pList);
BOOL ControlListAppend(CONTROL_LIST* pList, HWND hWnd);
<span class="code-keyword">void</span> ControlListRemove(CONTROL_LIST* pList, HWND hWnd);
BOOL ControlListContains(CONTROL_LIST* pList, HWND hWnd);
BOOL ControlListEmpty(CONTROL_LIST* pList);

<span class="code-comment">//</span><span class="code-comment"> Parent window subclass procedure. For messages which may need the reflection, it consults</span>
<span class="code-comment">//</span><span class="code-comment"> the list of controls and, according to the result, it either does the reflection or calls</span>
<span class="code-comment">//</span><span class="code-comment"> the original parent window procedure.</span>
<span class="code-keyword">static</span> LRESULT CALLBACK
ParentSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwData)
{
    CONTROL_LIST* pControlList = (CONTROL_LIST*) dwData;
    UINT i;

    <span class="code-comment">//</span><span class="code-comment"> Reflect the message (if needed):</span>
    <span class="code-keyword">switch</span>(uMsg) {
        <span class="code-keyword">case</span> WM_NOTIFY:
        {
            NMHDR* nmhdr = (NMHDR*) lParam;

            <span class="code-keyword">if</span>(ControlListContains(pControlList, nmhdr-&gt;hwndFrom))
                <span class="code-keyword">return</span> SendMessage(nmhdr-&gt;hwndFrom, uMsg + OCM__BASE, wParam, lParam);
            <span class="code-keyword">break</span>;
        }

        <span class="code-comment">//</span><span class="code-comment"> All of these provide the control's HHWND in LPARAM</span>
        <span class="code-keyword">case</span> WM_COMMAND:
        <span class="code-keyword">case</span> WM_CTLCOLORBTN:
        <span class="code-keyword">case</span> WM_CTLCOLOREDIT:
        <span class="code-keyword">case</span> WM_CTLCOLORDLG:
        <span class="code-keyword">case</span> WM_CTLCOLORLISTBOX:
        <span class="code-keyword">case</span> WM_CTLCOLORMSGBOX:
        <span class="code-keyword">case</span> WM_CTLCOLORSCROLLBAR:
        <span class="code-keyword">case</span> WM_CTLCOLORSTATIC:
        <span class="code-keyword">case</span> WM_VKEYTOITEM:
        <span class="code-keyword">case</span> WM_CHARTOITEM:
            <span class="code-keyword">if</span>(ControlListContains(pControlList, (HWND) lParam)
                <span class="code-keyword">return</span> SendMessage((HWND) lParam, uMsg + OCM__BASE, wParam, lParam);
            <span class="code-keyword">break</span>;

        <span class="code-comment">//</span><span class="code-comment"> All of these provide ID of the control in WPARAM:</span>
        <span class="code-keyword">case</span> WM_DRAWITEM:
        <span class="code-keyword">case</span> WM_MEASUREITEM:
        <span class="code-keyword">case</span> WM_DELETEITEM:
        <span class="code-keyword">case</span> WM_COMPAREITEM:
            <span class="code-keyword">if</span>(wParam != <span class="code-digit">0</span>) {
                HWND hwndControl = GetDlgItem(hwnd, wParam);
                <span class="code-keyword">if</span>(ControlListContains(pControlList, hwndControl)
                    <span class="code-keyword">return</span> SendMessage(hwndControl, uMsg + OCM__BASE, wParam, lParam);
            }
            <span class="code-keyword">break</span>;

        <span class="code-comment">//</span><span class="code-comment"> Note we do not reflect WM_PARENTNOTIFY -&gt; OCM_PARENTNOTIFY as that </span>
        <span class="code-comment">//</span><span class="code-comment"> usually does not make much sense.</span>
    }

    <span class="code-comment">//</span><span class="code-comment"> If not reflected, call the original parent procedure:</span>
    <span class="code-keyword">return</span> DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

<span class="code-comment">//</span><span class="code-comment"> The implementation of the customized control. </span>
<span class="code-comment">//</span><span class="code-comment"> Note that on creation/destruction we update the list of controls that need the message</span>
<span class="code-comment">//</span><span class="code-comment"> reflection and also we make sure that the parent is subclassed for the lifetime</span>
<span class="code-comment">//</span><span class="code-comment"> of the control. The subclass then does the reflection for us.</span>
<span class="code-keyword">static</span> LRESULT CALLBACK
ControlSuperclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    <span class="code-keyword">switch</span>(uMsg) {
        <span class="code-keyword">case</span> WM_NCCREATE:
        {
            CREATESTRUCT* pCs = (CREATESTRUCT*) lParam;
            CONTROL_LIST* pControlList;

            <span class="code-comment">//</span><span class="code-comment"> Ensure the parent window shall reflect notification to us:</span>
            <span class="code-keyword">if</span>(GetWindowSubclass(hWnd, ParentSubclassProc, <span class="code-digit">0</span>, (DWORD_PTR*) &amp;pControlList)) {
                <span class="code-keyword">if</span>(!ControlListAppend(pControlList, hWnd))
                    <span class="code-keyword">return</span> -<span class="code-digit">1</span>;
            } <span class="code-keyword">else</span> {
                pControlList = ControlListCreate();
                <span class="code-keyword">if</span>(pControlList == NULL)
                    <span class="code-keyword">return</span> -<span class="code-digit">1</span>;
                ControlListAppend(pControlList, hWnd);
                SetWindowSubclass(hWnd, ParentSubclassProc, <span class="code-digit">0</span>, (DWORD_PTR) pControlList);
            }

            <span class="code-comment">//</span><span class="code-comment"> Break to CallWindowProc() so the underlying control is properly </span>
            <span class="code-comment">//</span><span class="code-comment"> created and initialized:</span>
            <span class="code-keyword">break</span>;  
        }

        <span class="code-keyword">case</span> WM_NCDESTROY:
        {
            LRESULT lRes;
            CONTROL_LIST* pControlList;

            lRes = CallWindowProc(lpfnOriginalProc, hWnd, uMsg, wParam, lParam);

            GetWindowSubclass(hWnd, ParentSubclassProc, <span class="code-digit">0</span>, (DWORD_PTR*) &amp;pControlList);
            ControlListRemove(pControlList, hWnd);
            <span class="code-keyword">if</span>(ControlListEmpty(pControlList)) {
                ControlListDestroy(pControlList);
                RemoveWindowSubclass(GetParent(hWnd, ParentSubclassProc, <span class="code-digit">0</span>));
            }
            <span class="code-keyword">return</span> lRes;
        }

        <span class="code-comment">//</span><span class="code-comment"> Customize the underlying control as desired. We may handle the reflected </span>
        <span class="code-comment">//</span><span class="code-comment"> messages (OCM__xxx) as needed.</span>
        ....  
    }

    <span class="code-comment">//</span><span class="code-comment"> By default, propagate the message to the underlying control procedure:</span>
    <span class="code-keyword">return</span> CallWindowProc(lpfnOriginalProc, hWnd, uMsg, wParam, lParam);
}</pre>

<p>Obviously, the presented code fails if you ever attempt to reparent the control to another parent window with <code>SetWindowParent()</code>. Such support could be added at the cost of more complexity but, arguably, it is not worth of it. Especially when taking into account that most standard controls do not support it as explained in Raymond Chen's blog post <a href="http://blogs.msdn.com/b/oldnewthing/archive/2010/03/16/9979112.aspx">Why does my control send its notifications to the wrong window after I reparent it?</a>.</p>

<h2>Next Time: Scrolling Support and Non-client Area</h2>

<p>With this article we leave the topic of the control customization finally behind.</p>

<p>Next time we will take a look how to add a scrollbar support into your controland how to paint in a non-client area (especially with the respect to the visual styles). At first it may seem as two quite unrelated topics, but the connection does make a sense if you realize the scrollbars are part of the non-client area.</p>

<p>So stay tuned, this series is not yet coming to an end although the delay since the previous article took much more time then I anticipated. Hopefully the delay of the next article will be much shorter <img align="top" alt="Smile | :)" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/smiley_smile.gif"></p>


						</div>
						

						<div class="float-right" style="margin:20px 0 0 10px;border:1px solid #ccc">
						
						</div>
                        
                        
						
						<h2>License</h2>
						<div id="LicenseTerms"><p>This article, along with any associated source code and files, is licensed under <a href="http://www.codeproject.com/info/cpol10.aspx" rel="license">The Code Project Open License (CPOL)</a></p></div><h2 id="ctl00_AboutHeading">About the Author</h2>
						    

<div class="author-wrapper">

    <div class="pic-wrapper"> 
        <img id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberPhoto" class="profile-pic" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/58de2d085c17e28b8951315245dd408c.jpeg" style="border-width:0px;transform:rotate(1deg);">
    </div>

    <div class="container-member">  
        <b><a id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberProfileLink" class="author" href="https://www.codeproject.com/Members/Martin-Mitas">Martin Mitáš</a></b>

        <table>
        <tbody><tr>
            <td rowspan="2" nowrap="" valign="middle">
            <div id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_FollowOn" class="follow">
	            
	            
	            <a href="https://www.linkedin.com/profile/view?id=88607525"><img style="vertical-align:middle;border:0;height:24px;width:24px" alt="LinkedIn" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/linkedin-32.png"></a> 
            </div>
            </td>
            <td nowrap="nowrap">
                <div class="company">
                    <span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberJobTitle">Team Leader</span>
	                <span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberCompany"></span>
                </div>
            </td>
            <td rowspan="2" style="padding-left:15px">
                <a id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_FollowMember_FollowBtn" title="Have events related to this Member appear in your timeline" class="button unfollowed align-center invisible" data-enabletooltip="true" data-tooltip="Have the articles and posts from this member appear in your Timeline so you can stay up to date." style="display:none;">Follow<div class="tiny-text" style="margin-top:-3px;">this Member</div></a>
	<a id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_FollowMember_UnfollowBtn" title="Unfollow this Member" class="button followed align-center invisible" data-enabletooltip="true" data-tooltip="Stop following this Member" style="display:none;">Unfollow</a>

            </td>
        </tr>
        <tr>
            <td>
                <span id="ctl00_AboutAuthorRptr_ctl00_AboutAuthor_memberLocation">Czech Republic <img src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/CZ.gif" alt="Czech Republic" width="16px" height="11px"></span>
            </td>
        </tr>
        </tbody></table>
    </div>

    <div class="description">
        No Biography provided

        
    </div>

</div><br>
						
						

						<div class="clearfix"></div>

						<div style="padding-top:8px">
							
						</div>

					

				    
					</form>

				</div>

				
				<div class="bottom-promo"> 
				    
				</div>
				

                

				
				

					<h2>Comments and Discussions</h2>
					
					<p><img alt="Comment" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/NewComment.gif" width="12px" height="16px">
					<b>4 messages</b> have been posted for this article 
					Visit <b><a id="ctl00_ArticleLink" href="https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust">https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust</a></b> to post and view comments on 
					this article, or click <b><a id="ctl00_PrintWithMessage" href="https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust?display=PrintAll">here</a></b> 
					to get a print view with messages.</p>
					
				

			</div>
			
		</td>
		<td width="170px" class="article-wing-right">
			
		</td>
		</tr></tbody></table>

		
		<div class="theme1-background" style="height:2px" id="stickyStop"></div>

		<div class="extended tiny-text">
			<div class="row">
				<div class="float-left">
					<a id="ctl00_PermaLink" href="https://www.codeproject.com/Articles/744603/Custom-Controls-in-Win-API-Encapsulation-of-Cust">Permalink</a> | 
					<a id="ctl00_AdvertiseLink" href="http://developermedia.com/">Advertise </a> |
					<a id="ctl00_PrivacyLink" href="https://www.codeproject.com/info/privacy.aspx">Privacy</a> |
    				<a id="ctl00_CookiePolicyLink" href="https://www.codeproject.com/info/cookies.aspx">Cookies</a> |
                    <a id="ctl00_TermsOfUseLink" href="https://www.codeproject.com/info/TermsOfUse.aspx">Terms of Use</a> |
					<a id="ctl00_Mobile">Mobile</a>
					<br>
								
					
					Web06 |
					2.8.181119.1 |
					Last Updated 11 Dec 2014								
				</div>

                      

				<div class="float-right align-right">
					Article Copyright 2014 by Martin Mitáš<br>Everything else
					Copyright © <a href="mailto:webmaster@codeproject.com">CodeProject</a>, 1999-2018 <br>
				</div>

				

			</div>
		</div>
		

		<br clear="all">
		
			

	</div> 
	</div>
</div>






<script type="text/javascript" src="./Custom Controls in Win32 API_ Encapsulation of Customized Controls - CodeProject_files/MemberProfilePopup.min.js.下载"></script>
<script type="text/javascript">//<![CDATA[
$(document).ready(function () {
   processCodeBlocks.Initialise('#contentdiv');
   thumbnailer.Initialise('#contentdiv',700,600);
});
cookieconsent.initialise({
                                enabled : true,
                                cookie  : { domain: 'codeproject.com' },
                                palette : {
                                    popup: { background: '#ff9900' },
                                    button: { background: '#f5d948' }
                                },
                                law :  {
                                    showForAllRegions : true, 
                                    countryCode : 'CN' 
                                },
                                theme: 'edgeless',
                                type : 'opt-in',
                                content: {
                                    message: 'Like every other website we use cookies. By using our site you acknowledge that you have read and understand our <a href=\'/info/cookie.aspx\'>Cookie Policy</a>, <a href=\'/info/privacy.aspx\'>Privacy Policy</a>, and our <a href=\'/info/TermsOfUse.aspx\'>Terms of Service</a>.',
                                    href:    'https://www.codeproject.com/info/privacy.aspx'
                                },
                                revokable:true,
                                onStatusChange: function(status) {
                                    $.ajax({
                                		dataType  : 'json',
                                        data: JSON.stringify({ allowCookies : this.hasConsented() }),
                                        url: '/script/Common/webservices/CommonServices.aspx/SetCookieConsent',
                                        cache: false,
                                        type: 'POST',
                                        contentType: 'application/json'
                                    })
                                    console.log(this.hasConsented() ? 'enable cookies' : 'disable cookies');
                                    console.log(this.hasAnswered() ? 'has answered' : 'did not answer');
                                },
                            });
$(document).ready(function() { anchorAnimate();
});
$(document).ready(function(){
    $('#__EVENTVALIDATION').attr('autocomplete', 'off');
});
$(function() {
                        var followServicectl00_AboutAuthorRptr_ctl00_AboutAuthor_FollowMember = new FollowService('/script/follow/webservices/followServices.aspx/', true);
                        followServicectl00_AboutAuthorRptr_ctl00_AboutAuthor_FollowMember.initFollowObjectButtons({
                            item : { 
                                objectTypeId   : 1,
                                objectId       : 5807385
                            },
                            followButtonId   : 'ctl00_AboutAuthorRptr_ctl00_AboutAuthor_FollowMember_FollowBtn',
                            unfollowButtonId : 'ctl00_AboutAuthorRptr_ctl00_AboutAuthor_FollowMember_UnfollowBtn'
                        }, false);
                    });

//]]>
</script>





<div id="MemberProfilePopupDiv" class="raised box" style="display: none; position: absolute;"></div><div id="MemberProfilePopupDiv" class="raised box" style="display: none; position: absolute;"></div><div id="MemberProfilePopupDiv" class="raised box" style="display: none; position: absolute;"></div></body></html>